package com.wsj.common.security;

public class Des
{
    static int[] ls_count = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
    static int[] pc_1_c={57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36};
    static int[] pc_1_d={63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4};
    static int[] pc_2={14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32};
    static int[] ip_tab={58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7};
    static int[] _ip_tab={40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,34,2,42,10,50,18,58,26,33,1,41,9,49,17,57,25};

    static int[] e_r={
	32,1,2,3,4,5,4,5,6,7,8,9,
	8,9,10,11,12,13,12,13,14,15,16,17,
	16,17,18,19,20,21,20,21,22,23,24,25,
	24,25,26,27,28,29,28,29,30,31,32,1};

    static int[] P={
	16,7,20,21,29,12,28,17,
	1,15,23,26,5,18,31,10,
	2,8,24,14,32,27,3,9,
	19,13,30,6,22,11,4,25};
    static int[][][] SSS={
	{{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},
	{0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},/* err on */
	{4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},
	{15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}},

	{{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},
	{3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},
	{0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},
	{13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}},

	{{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},
	{13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},
	{13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},
	{1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}},

	{{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},
	{13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},
	{10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},
	{3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}}, /* err on */

	{{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},
	{14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6}, /* err on */
	{4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},
	{11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}},

	{{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},
	{10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},
	{9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},
	{4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}},

	{{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},
	{13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},
	{1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},
	{6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}},

	{{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},
	{1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},
	{7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},
	{2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}
};

    char[][] C, D, K;
    public Des()
    {
        C = new char[17][28];
        D = new char[17][28];
        K = new char[17][48];
    }

    public byte[] Do_XOR( byte[] hex1, byte[] hex2, int num )
    {
        int i;
        byte[] dest = new byte[num];

        for ( i = 0; i < num; i++ )
          dest[i] = hex1[i] ^= hex2[i];
        return dest;
    }

    public byte[] DSP_2_HEX( String dsp,  int num )
    {
        byte[] hex = new byte[num];
        for (int i = 0; i < num; i++ )
        {
            char ch = dsp.charAt(i*2);
	    hex[ i ] = (byte)( ( ch <= '9' ) ? ch - '0' : ch - 'A' + 10 );
            hex[ i ] = (byte)((int)hex[ i ] << 4);
            ch = dsp.charAt(i*2 + 1);
            hex[ i ] += (byte)( ( ch <= '9' ) ? ch - '0' : ch - 'A' + 10 );
        }
        return hex;
    }

    public String HEX_2_DSP( byte[] hex, int num )
    {
        String dsp="";
        char ch[] = new char[2*num];
        for( int i = 0; i < num; i++ )
        {
            byte bt = (byte)((((int)hex[ i ]) & 0xf0 ) >> 4);
            ch[ i * 2 ] = (char)(( bt > 9 ) ? bt + 'A' - 10 : bt + '0');
            bt = (byte) (((int)hex[ i ]) & 0x0f);
            ch[ i * 2 + 1 ] = (char)(( bt > 9 ) ? bt + 'A' - 10 : bt + '0');
        }
        dsp = String.copyValueOf(ch);
        return dsp;
    }

    private char[] expand0(char[] in)
    {
        int divide;
        char out[] = new char[64];
        int k = 0;

	for (int i=0; i<8; i++)
	{
	    divide = 0x80;
            for (int j=0; j<8; j++)
	    {
	        out[k++] =(char)(((int)in[i]/divide)&1);
		divide /= 2;
            }
	}
        return out;
    }

    private void LS(char[] bits, char[] buffer, int count)
    {
	for (int i=0; i<28; i++)
	{
            buffer[i] = bits[(i+count)%28];
	}
    }

    private void son(char[] cc, char[] dd, char[] kk)
    {
	int i;
	char[] buffer = new char[56];
	for (i=0;i<28;i++)
            buffer[i] = cc[i];

	for (i=28;i<56;i++)
            buffer[i] = dd[i-28];

	for (i=0;i<48;i++)
            kk[i] = buffer[pc_2[i]-1];
    }

    private void setkeystar(char[] bits)
    {
	int i,j;

	for (i=0; i<28; i++)
		C[0][i] = bits[pc_1_c[i]-1];
	for (i=0; i<28; i++)
		D[0][i] = bits[pc_1_d[i]-1];
	for (j=0; j<16; j++)
	{
            LS(C[j],C[j+1],ls_count[j]);
            LS(D[j],D[j+1],ls_count[j]);
            son(C[j+1],D[j+1],K[j+1]);
	}
    }

    private char[] ip(char[] text)
    {
	char[] buffer = new char[64];
	buffer = expand0(text);
        return buffer;
    }

    private char[] s_box(char[] aa)
    {
	int i,j,k,m;
	int y,z;
        char[] bb = new char[64];
	char[] ss = new char[8];

	m=0;
	for (i=0; i<8; i++)
	{
            j = 6*i;
	    y = aa[j]*2+aa[j+5];
	    z = aa[j+1]*8+aa[j+2]*4+aa[j+3]*2+aa[j+4];
	    ss[i] = (char)SSS[i][y][z];
	    y = 0x08;
	    for (k=0; k<4; k++)
	    {
	        bb[m++]=(char)(((int)ss[i]/y)&1);
		y/=2;
            }
	}
        return bb;
    }

    private char[] F(int n, char[] ll, char[] rr)
    {
	int i;
	char[] buffer = new char[64];
        char[] tmp = new char[64];

	for (i=0;i<48;i++)
		buffer[i]=rr[e_r[i]-1];
	for (i=0;i<48;i++)
		buffer[i]=(char)((buffer[i]+K[n][i])&1);

      	tmp = s_box(buffer);

	for (i=0;i<32;i++)
		buffer[i] = tmp[P[i]-1];

        return buffer;
    }

    static char[] _ip(char[] ll, char[] rr)
    {
	int i;
	char[] tmp = new char[64];
	char[] text = new char[64];

	for (i=0;i<32;i++)
	    tmp[i] = ll[i];
	for (i=32;i<64;i++)
            tmp[i] = rr[i-32];
	for (i=0; i<64; i++)
            text[i] = tmp[_ip_tab[i]-1];
        return text;
    }

    private char[] compress0(char[] out)
    {
	int times;
	int i,j;
        int k=0;
        char[] in = new char[8];

	for (i=0;i<8;i++)
	{
	    times = 0x80;
	    in[i] = 0;
	    for (j=0; j<8; j++)
	    {
	    	in[i] += (char)((out[k++])*times);
	    	times/=2;
	    }
	}
        return in;
    }

    private char[] discrypt0(char[] mtext)
    {
	char[] ll = new char[64];
	char[] rr = new char[64];
	char[] LL = new char[64];
	char[] RR = new char[64];
	char[] tmp = new char[64];
	char[] str = new char[64];
	int i,j;

	str = ip(mtext);
	for (i=0;i<32;i++)
	    ll[i] = str[ip_tab[i]-1];

	for (i=0;i<32;i++)
	    rr[i] = str[ip_tab[i+32]-1];

	for (i=16; i>0; i--)
	{
            str = F(i, ll, rr);
            for (int ii = 0; ii < 32; ii++)
		LL[ii]=(char)((str[ii]+ll[ii])&1);

            for (int ii = 0; ii < 32; ii++)
	        RR[ii] = rr[ii];

	    for (j=0; j<32; j++)
	    {
	    	ll[j] = LL[j];
	    	rr[j] = RR[j];
	    }
	}

	tmp = _ip(rr,ll);

	str = compress0(tmp);
        return str;
    }

    private char[] encrypt0(char[] text)
    {
	char[] ll = new char[64];
	char[] rr = new char[64];
	char[] LL = new char[64];
	char[] RR = new char[64];
	char[] tmp = new char[64];
	char[] str = new char[64];

	int i,j;
	str = ip(text);

	for (i=0;i<32;i++)
	    ll[i] = str[ip_tab[i]-1];

	for (i=0;i<32;i++)
	    rr[i] = str[ip_tab[i+32]-1];

	for (i=1;i<17;i++)
	{
            str = F(i, ll, rr);
            for (int ii = 0; ii < 32; ii++)
		RR[ii]=(char)((str[ii]+ll[ii])&1);

            for (int ii = 0; ii < 32; ii++)
		LL[ii] = rr[ii];

            for (j=0; j<32; j++)
            {
	        ll[j] = LL[j];
		rr[j] = RR[j];
            }
	}
	tmp = _ip(rr,ll);

	str = compress0(tmp);
        return str;
    }

    public char[] DoDes(char[] source, char[] key, char flag)
    {
        char[] tmp = new char[64];
        char[] dest = new char[8];
        tmp = expand0(key);
        setkeystar(tmp);
        switch (flag)
        {
        case 'e':
        case 'E':
            dest = encrypt0(source);
            break;
        case 'D':
        case 'd':
            dest = discrypt0(source);
            break;
        default:
            for (int i=0; i<8; i++)
                dest[i] = 0;
            break;
        }
        return dest;
    }

    private byte[] PasswdDes(String strPwd)
    {
        char[] MKey = new char[8];
        char[] Sour = new char[8];
        char[] Dest = new char[8];
        for (int ii=0; ii < strPwd.length(); ii++)
            Sour[ii] = strPwd.charAt(ii);
        for (int k = strPwd.length(); k<8; k++)
            Sour[k] = (char)0x00;

        MKey[0] = 0x12;
        MKey[1] = 0x34;
        MKey[2] = 0x56;
        MKey[3] = 0x78;
        MKey[4] = 0x90;
        MKey[5] = 0xAB;
        MKey[6] = 0xCD;
        MKey[7] = 0xEF;

        Dest = DoDes(Sour, MKey, 'E');
        byte[] bt = new byte[8];
        for (int i=0; i<8; i++)
            bt[i] = (byte)Dest[i];
        return bt;
    }

    public String Encrypt( String passwd )
    {
        String strDestPwd;
    	byte[] bt;
    	bt = PasswdDes( passwd );
        strDestPwd = HEX_2_DSP(bt, 8);

        return strDestPwd;
    }
    public static void main(String[] args)
    {
        Des d =new Des();
        d.Encrypt("");
    }
  /**
   *����Ա�������
   * @param p_oper     :����Ա����
   * @param p_creditNo :����Ա���
   * @param p_oldPwd   :����ǰ����
   * @return
   */
  public static String InitOperPwd(String p_oper,String p_creditNo,String p_oldPwd)
  {
     char[] tmpArray = new char[8];
     char[] srcChar = new char[8];
     char[] keyChar = new char[8];
     byte[] msrc1 = new byte[8];
     byte[] msrc2 = new byte[8];
     byte[] src = new byte[8];
     byte[] dest =new byte[8];
     byte[] key =new byte[8];
     String tmp = "";

     Des m_Des =new Des();
     // ��ɲ���Ա��ʼ����

     key = m_Des.DSP_2_HEX(SysVal.PCS_KEY,8) ;

     tmp = formatStr(p_oper,6,1) ;
     tmp += formatStr(p_creditNo,10,1);
     msrc1 = m_Des.DSP_2_HEX(tmp,8) ;

     tmp = formatStr(p_oldPwd,8,1);
     tmp += formatStr(String.valueOf(p_oldPwd.length()),8,1);

     msrc2 = m_Des.DSP_2_HEX(tmp,8) ;

     src = m_Des.Do_XOR( msrc1, msrc2,8 ) ;

     for(int i=0;i<8;i++)
     {
         srcChar[i] = (char) src[i];
         keyChar[i] = (char) key[i];
     }
     tmpArray = m_Des.DoDes( srcChar,keyChar,'e');
     for(int i=0;i<8;i++)
       dest[i] =(byte) tmpArray[i];

     tmp = m_Des.HEX_2_DSP(dest,8);

     return tmp;
    }
  /**
   * �ַ��ʽ��
   * @param p_str    :Դ�ַ�
   * @param p_len    :��Ҫ�ĳ���
   * @param p_aspect :��λ����
   * @return
   */
  private static String formatStr(String p_str,int p_len,int p_aspect)
  {
	  StringBuffer bufftmp=new StringBuffer("");
//      String tmp ="";
      int longth =0;

      longth = p_str.length();
      if(p_len <= longth)
        return p_str;
      bufftmp.append(p_str);
//      tmp = p_str ;
      //p_aspect:0 ��������ұ߲��㲹0��1 :���Ҷ�����߲�0
      switch(p_aspect )
      {
        case 0 :
               for(int i=0;i<p_len -longth;i++)
            	   bufftmp.append("0") ;
//                 tmp +="0";
               break;
        case 1 :
               for(int i=0;i<p_len -longth;i++)
            	   bufftmp.append("0");
//                 tmp ="0" + tmp;
               break;
         default :
           return bufftmp.toString();
      }
      return bufftmp.toString() ;
  }
}